# encoding: utf-8
"""
    IM客户端
"""
import msgpack
import socket
import threading
import time
import ssl
import threadpool

from qa.IM import qasql
from convert import Convert

__author__ = 'jiaoshupeng'


class ClientIM:
    # 批量给同一个账号发送消息
    def __init__(self, username, password, num, connect_num, uid):
        # 设置聊天host和port
        self.chart_host = '106.75.109.100'
        self.chat_port = 8080
        self.classCon = Convert(username, password)
        self.num = num
        self.connect_num = connect_num
        self.uid = uid

    def socket_im(self):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect((self.chart_host, self.chat_port))
        try:
            sendData = self.classCon.getStart()
            if sendData == 0:
                return
            # 定义鉴权包
            self.sock.send(bytearray(sendData))
            # 发送鉴权包
            reply = self.sock.recv(16)
            getHeader = self.headerByte(reply)
            # 获取鉴权头
            if getHeader == '00010010':  # 判断鉴权是否成功
                print '鉴权成功'
                threads = []
                # 发送消息
                sendMsg = threading.Thread(target=self.sendMsg, args=())
                threads.append(sendMsg)
                # 接收消息
                # 后期需要释放------------************------------
                recMsg = threading.Thread(target=self.recMsg, args=())
                threads.append(recMsg)
                # self.sync()
                for thread in threads:
                    thread.setDaemon(True)
                    thread.start()
                thread.join()
            else:
                print '连接断开'
                return False
        finally:
            self.sock.close()

    def headerByte(self, reply):  # 解析头部
        getReply = bytearray(reply)
        head = bin(getReply[0]).replace('0b', '').zfill(8)
        return head

    def pingByte(self, reply):
        # print reply
        header = bin(reply[0]).replace('0b', '').zfill(8)
        try:
            if header == '00101001':  # 心跳包只包含头
                try:
                    dataByte = []
                    for num in range(8):
                        data = bin(reply[num]).replace('0b', '').zfill(8)
                        dataByte.append(data)
                    version = self.montage(dataByte[1])
                    messageLen = self.montage(dataByte[2:6])
                    pingTime = self.montage(dataByte[6:8])
                    result = '接收到服务器发送的心跳包,心跳包版本为%d,消息体长度为%d,间隔时间为%d秒' % (version, messageLen, pingTime)
                except:
                    result = '接收到服务器发送的心跳包,心跳包仅包含header'
            elif header == '00111010':  # 消息送达成功
                arrMsg = []
                for num in range(0, 23):
                    dataMsg = bin(reply[num]).replace('0b', '').zfill(8)
                    arrMsg.append(dataMsg)
                header = arrMsg[0]
                version = int(arrMsg[1], 2)
                msgLenth = int(''.join(arrMsg[2:6]), 2)
                res = int(arrMsg[6], 2)
                localId = int(''.join(arrMsg[7:11]), 2)
                if res == 0:
                    result = '消息成功送达,header为%s, 版本为%s, 消息长度为%s, local ID为%s' % (header, version, msgLenth, localId)
                else:
                    result = '消息送达失败, header为%s, 版本为%s, 消息长度为%s' % (header, version, msgLenth)
            elif header == '01001000':
                if len(reply) == 20:
                    result = '您的消息已被对方查看'
                else:
                    result = self.getServerReply(reply)
            elif header == '00100001':
                result = '接收到服务器不带有payloads PING'
                pingData = bytearray(self.classCon.ping(1))
                self.sock.send(pingData)
            elif header == '01011110' or header == '01100100' or header == '10100000' or header == '00110010':
                print reply
            else:
                print header
                result = '服务器断开连接'
            return result
        except:
            print '服务端返回信息读取失败'

    def montage(self, values):
        if type(values) == str:
            result = values
        else:
            result = ''.join(values)
        res = int(result, 2)
        return res

    def sendMsg(self):
        num = 0
        time.sleep(0)
        # while True:
        #     try:
        #         num += 1
        #         # 批量给一个群发送消息
        #         guestUid = '12504'  # 接受消息时用户的uid   12505 12506
        #         msgContents = '测试数据第%d条数据'%self.num  # 发送的内容
        #         msgData = bytearray(self.classCon.sendmsg_groups(int(guestUid), msgContents))
        #         self.sock.send(msgData)
        #         if num == 1:  # 给同一个接受用户发送消息的数量
        #             break
        #     except:
        #         print "用户UID不存在,请输入正确的UID"
        while True:
            # try:
            # 批量给同一个账号发送消息
            guestUid = str(self.uid)  # 接受消息时用户的uid
            msgContents = '测试数据第%d条' % num  # 发送的内容
            msgData = bytearray(self.classCon.sendWord(int(guestUid), msgContents))
            self.sock.send(msgData)
            num += 1
            time.sleep(1)
            if num == self.connect_num:  # 给同一个接受用户发送消息的数量
                break
                # except:
                #     print "用户UID不存在,请输入正确的UID"

    def recMsg(self):
        n = 0
        while True:
            try:
                ping = self.recv_basic()
                getPing = bytearray(ping)
                header = bin(getPing[0]).replace('0b', '').zfill(8)
                if header == '00101001':
                    print self.pingByte(getPing)
                    pingData = bytearray(self.classCon.ping(1))
                    self.sock.send(pingData)
                else:
                    n += 1
                    print self.pingByte(getPing)
                    if n == self.connect_num:
                        return False
            except:
                print '程序出错'
                return False

    def sync(self):
        msgData = bytearray(self.classCon.sync())
        self.sock.send(msgData)

    def recv_basic(self):
        data = self.sock.recv(8192)
        return data

    def getServerReply(self, reply):
        arrMsg = []
        for num in range(0, len(reply)):
            dataMsg = bin(reply[num]).replace('0b', '').zfill(8)
            arrMsg.append(dataMsg)
        # s_type = MessageType().session_list(int(arrMsg[7], 2))  # 会话类型
        binMsg = ''.join(arrMsg[28:])
        strMsg = msgpack.unpackb(Convert().restore(binMsg))
        name = strMsg['profile']['name']
        contents = strMsg['contents']
        # m_type = MessageType().message_list(strMsg['type'])  # 消息类型
        # return '%s 给您发来%s,消息类型为:%s 消息内容为:%s' % (name, s_type, m_type, contents)


def main(all_num, connect_num, uid):
    # a = ClientIM("2574006368@qq.com", '123456', num=0)
    # a.socket_im()
    # for i in range(3):
    list_user = []
    user = qasql.sel(all_num)
    print user
    for users in user:
        list_user.append(list(users))
    num = 0

    def getstart(user_data):
        username = user_data[0]
        password = user_data[1]
        num = int(time.time())
        a = ClientIM(username, password, num, connect_num, uid)
        a.socket_im()

    pool = threadpool.ThreadPool(100)
    requests = threadpool.makeRequests(getstart, list_user)
    [pool.putRequest(req) for req in requests]
    pool.wait()
    return 'success'


# print main(1, 2, 9334493)
# for user_data in user:
#     print user_data[0]
#     username = user_data[0]
#     password = user_data[1]
#     num += 1
#     a = ClientIM(username, password, num)
#     a.socket_im()
